from __future__ import annotations

import json
import re
from typing import Dict, List

from loguru import logger
from pydantic import BaseModel, ValidationError


class WxAlbumInfo(BaseModel):
    album_id: str = ""
    album_title: str = ""
    album_cover: str = ""
    album_description: str = ""
    album_tags: list = []
    album_count: int = 0
    item: List[WxAlbumInfo] = []

    def to_json(self) -> str:
        return json.dumps(self.model_dump(), ensure_ascii=False, indent=2)


class WxImage(BaseModel):
    media_id: str = ""
    name: str = ""
    update_time: int = 0
    url: str = ""
    tags: List[str] = []

    def __eq__(self, other):
        if not isinstance(other, WxImage):
            return NotImplemented
        return (
            self.media_id == other.media_id
            and self.name == other.name
            and self.update_time == other.update_time
            and self.url == other.url
            and sorted(self.tags) == sorted(other.tags)
        )

    def __hash__(self):
        # tags 需要无序 hash，可以用 frozenset
        return hash(
            (self.media_id, self.name, self.update_time,
             self.url, frozenset(self.tags))
        )

    @staticmethod
    def fromJson(data: Dict) -> WxImage:
        try:
            return WxImage.model_validate(data)
        except ValidationError:
            logger.error(f"数据格式或内容不合法:{data}")
            return WxImage.EMPTY_IMAGE


WxImage.EMPTY_IMAGE = WxImage()


class WxImageList(BaseModel):
    total_count: int = 0
    item_count: int = 0
    item: List[WxImage] = []

    def __eq__(self, other):
        if not isinstance(other, WxImageList):
            return NotImplemented
        return (
            self.total_count == other.total_count
            and self.item_count == other.item_count
            and len(self.item) == len(other.item)
            and set(self.item) == set(other.item)
        )

    @staticmethod
    def fromJson(data: Dict) -> WxImageList:
        try:
            return WxImageList.model_validate(data)
        except ValidationError:
            logger.error(f"数据格式或内容不合法:{data}")
            return WxImageList.ERROR_LIST

    def merge(self, other: "WxImageList") -> WxImageList:
        """
        合并 other 的 item 到 self.item，去重，更新 item_count，total_count 取最大值。
        """
        # 利用 set 去重，前提是 WxImage 已实现 __eq__ 和 __hash__
        merged_set = set(self.item) | set(other.item)
        self.item = list(merged_set)
        self.item_count = len(self.item)
        self.total_count = max(self.total_count, other.total_count)
        return self

    def to_json(self) -> str:
        return json.dumps(self.model_dump(), ensure_ascii=False, indent=2)


WxImageList.ERROR_LIST = WxImageList.fromJson(
    {"total_count": -1, "item_count": -1, "item": []}
)


class WxArticlePublished(BaseModel):
    title: str = ""
    author: str = ""
    publish_time: str = ""
    content_html: str = ""
    img_links: list[str] = []


class WxContentSecurity(BaseModel):
    """原创声明配置"""

    content_security_type: int = 0
    need_open_original: bool = True
    user_declare_type: int = 0
    original_platform_list: list = []


class WxArticleBrief(BaseModel):
    media_id: str = ""
    title: str = ""
    tags: list = []
    album_id: str = ""
    album_title: str = ""


WxArticleBrief.EMPTY = WxArticleBrief()


class WxArticle(BaseModel):
    media_id: str = ""
    title: str = ""
    author: str = ""
    digest: str = ""
    show_cover_pic: int = 1  # Display cover picture
    url: str = ""
    content: str = ""
    content_source_url: str = ""
    need_open_comment: int = 1
    thumb_media_id: str = ""
    article_subject_id: str = ""
    content_security_declaration: WxContentSecurity = WxContentSecurity()
    create_time: int = -1
    update_time: int = -1

    def get_id(self) -> str:
        # parses url to get article_id
        if not self.url:
            return ""
        # 匹配 /s/ 后面的内容，直到遇到下一个 / 或 ? 或 # 或字符串结尾
        match = re.search(r"/s/([^/?#]+)", self.url)
        if match:
            return match.group(1)
        return ""


class WxArticleList(BaseModel):
    total_count: int = 0
    item_count: int = 0
    item: List[WxArticle] = []

    def to_json(self) -> str:
        return json.dumps(self.model_dump(), ensure_ascii=False, indent=2)


WxArticleList.ERROR = WxArticleList(total_count=-1, item_count=-1, item=[])


if __name__ == "__main__":
    image_dict = {
        "media_id": "lqyPIeOizCBULZAmK9Tfvrq24shsptkh7rvzXHJGvl3WVqmgjRQz6hSXbesOw9M9",
        "name": "how-to-lead-saas-startup.png",
        "update_time": 1750253166,
        "url": "https://mmbiz.qpic.cn/mmbiz_png/YHiaESnpiaFDCbgZtSIEwyNPckQicbycHAcPJ4WRUibOznVJNjqRooickqzuFiayqh7PasRV3FgJgOCt5jeS007N9YJw/0?mdtool.fmt=png",
        "tags": [],
    }
    wx_image = WxImage(**image_dict)

    images_dict = {"item": [image_dict], "total_count": 1315, "item_count": 20}
    wx_image_list = WxImageList(**images_dict)
